home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / vopl / glvopl.lha / glvopl / src / scalers.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-29  |  6.3 KB  |  372 lines

  1. #include "vopl.h"
  2.  
  3. extern    double    pow();
  4. extern    double    log10();
  5. static    float    del = 0.000002;
  6.  
  7. /*
  8.  * ten2pow
  9.  *
  10.  *    Computes 10 to the power of i
  11.  */
  12. static float
  13. ten2pow(i)
  14.     int    i;
  15. {
  16.     float    a = 1.0;
  17.     int    j;
  18.  
  19.     if (i > 0)
  20.         for (j = 0; j < i; j++)
  21.             a *= 10.0;
  22.     else if (i < 0) 
  23.         for (j = 0; j > i; j--)
  24.             a /= 10.0;
  25.  
  26.     return (a);
  27. }
  28.     
  29. /*
  30.  * Algorithm 463 - scale3. (From CACM)
  31.  *
  32.  * given xmin , xmax and n, where n is greater than 1, scale3
  33.  * finds a new range xminp and xmaxp divisible into exactly
  34.  * n LOGARITHMIC intervals, where the ratio of adjacent
  35.  * uniformly spaced scale values is dist.
  36.  */
  37. void
  38. logscale(xmin, xmax, n , xminp, xmaxp, dist)
  39.     float    xmin, xmax;
  40.     int    n;
  41.     float    *xminp, *xmaxp, *dist;
  42. {
  43.     static    float vint[11] = {
  44.         10.0, 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.5
  45.     };
  46.  
  47.     float    xminl, xmaxl, fn, a, al, b, distl, fm1, fm2;
  48.     int    nal, i, m1, m2, np, nx;
  49.  
  50.     /*
  51.      * Check whether proper input values were supplied.
  52.      */
  53.     if (xmin >= xmax || n <= 0 || xmin <= 0.0) {
  54.         printf("logscale: Improper values supplied as input\n");
  55.         if (xmin <= 0.0)
  56.             printf("Zero or negative minimum value input: %f\n", xmin);
  57.  
  58.         exit(1);
  59.     }
  60.  
  61.     /*
  62.      * Values are translated from the linear region to the logarithmic
  63.      */
  64.     
  65.     xminl = (float)log10((double)xmin);
  66.     xmaxl = (float)log10((double)xmax);
  67.     fn = (float)n;
  68.  
  69.     /*
  70.      * Find approximate interval size a
  71.      */
  72.  
  73.     a = (xmaxl - xminl) / fn;
  74.     al = (float)log10((double)a);
  75.     nal = (int)al;
  76.     if (a < 1.0)
  77.         nal--;
  78.  
  79.     /*
  80.      * A is scaled into the variable named b between 1 and 10
  81.      */
  82.  
  83.     b = a / ten2pow(nal);
  84.  
  85.     /*
  86.      * The closest permissible value for b is found
  87.      */
  88.     
  89. /*
  90.     for (i = 0; i < 9 && b < (10.0 / vint[i] + del); i++)
  91.         ;
  92. */
  93.     for (i = 0; i < 9; i++)
  94.         if (b < (10.0 / vint[i] + del)) goto l1;
  95.  
  96.     i = 9;
  97. l1:
  98.     /*
  99.      * The interval size is computed
  100.      */
  101.     
  102.     do {
  103.         distl = ten2pow(nal + 1) / vint[i];
  104.         fm1 = xminl / distl;
  105.         m1 = (int)fm1;
  106.     
  107.         if (fm1 < 0.0) 
  108.             m1--;
  109.  
  110.         if (ABS((float)m1 + 1.0 - fm1) < del)
  111.             m1--;
  112.  
  113.         /*
  114.          * The new minimum and maximum limits are found
  115.          */
  116.  
  117.         *xminp = distl * (float)m1;
  118.  
  119.         fm2 = xmaxl / distl;
  120.         m2 = (int)(fm2 + 1.0);
  121.         if (fm2 < -1.0)
  122.             m2--;
  123.     
  124.         if (ABS(fm2 + 1.0 - (float)m2) < del)
  125.             m2--;
  126.  
  127.         *xmaxp = distl * (float)m2;
  128.  
  129.  
  130.         /*
  131.          * Check whether another pass is necessary
  132.          */
  133.         np = m2 - m1;
  134.         i++;
  135.     } while (np > n);
  136.  
  137.     nx = (n - np) / 2;
  138.     *xminp = *xminp - (float)nx * distl;
  139.     *xmaxp = *xminp + (float)n * distl;
  140.  
  141.     /*
  142.      * Values are translated from the logarithmic into the
  143.      * linear region.
  144.      */
  145.     
  146.     /**dist = (float)pow((double)10.0, (double)distl);*/
  147.     *dist = distl;
  148.     *xminp = (float)pow((double)10.0, (double)*xminp);
  149.     *xmaxp = (float)pow((double)10.0, (double)*xmaxp);
  150.  
  151.     /*
  152.      * Adjust limits to account for round-off if necessary
  153.      */
  154.  
  155.     if (*xminp > xmin)
  156.         *xminp = xmin;
  157.  
  158.     if (*xmaxp < xmax)
  159.         *xmaxp = xmax;
  160.  
  161. }
  162.  
  163.  
  164. /*
  165.  * Algorithm 463 - scale2. (From CACM)
  166.  *
  167.  * given xmin , xmax and n, where n is greater than 1, scale2
  168.  * finds a new range xminp and xmaxp divisible into exactly
  169.  * n LINEAR intervals of size dist, where n is greater than 1.
  170.  */
  171. void
  172. linscale2(xmin, xmax, n , xminp, xmaxp, dist)
  173.     float    xmin, xmax;
  174.     int    n;
  175.     float    *xminp, *xmaxp, *dist;
  176. {
  177.     static    float vint[5] = {
  178.         1.0, 2.0, 5.0, 10.0, 20.0
  179.     };
  180.  
  181.     float    fn, a, al, b, fm1, fm2;
  182.     int    nal, i, m1, m2, np, nx;
  183.  
  184.     /*
  185.      * Check whether proper input values were supplied.
  186.      */
  187.     if (xmin >= xmax || n <= 0) {
  188.         printf("linscale2: improper values supplied as input\n");
  189.         exit(1);
  190.     }
  191.  
  192.     fn = (float)n;
  193.  
  194.     /*
  195.      * Find approximate interval size a
  196.      */
  197.  
  198.     a = (xmax - xmin) / fn;
  199.     al = (float)log10((double)a);
  200.     nal = (int)al;
  201.     if (a < 1.0)
  202.         nal--;
  203.  
  204.     /*
  205.      * A is scaled into the variable named b between 1 and 10
  206.      */
  207.  
  208.     b = a / ten2pow(nal);
  209.  
  210.     /*
  211.      * The closest permissible value for b is found
  212.      */
  213.     
  214.     for (i = 0; i < 3 && b < (vint[i] + del); i++)
  215.         ;
  216.  
  217.     /*
  218.      * The interval size is computed
  219.      */
  220.     
  221.     do {
  222.         *dist = ten2pow(nal) * vint[i];
  223.         fm1 = xmin / *dist;
  224.         m1 = (int)fm1;
  225.     
  226.         if (fm1 < 0.0) 
  227.             m1--;
  228.  
  229.         if (ABS((float)m1 + 1.0 - fm1) < del)
  230.             m1--;
  231.  
  232.         /*
  233.          * The new minimum and maximum limits are found
  234.          */
  235.  
  236.         *xminp = *dist * (float)m1;
  237.  
  238.         fm2 = xmax / *dist;
  239.         m2 = (int)(fm2 + 1.0);
  240.         if (fm2 < -1.0)
  241.             m2--;
  242.     
  243.         if (ABS(fm2 + 1.0 - (float)m2) < del)
  244.             m2--;
  245.  
  246.         *xmaxp = *dist * (float)m2;
  247.  
  248.  
  249.         /*
  250.          * Check whether another pass is necessary
  251.          */
  252.         np = m2 - m1;
  253.         i++;
  254.     } while (np > n);
  255.  
  256.     nx = (n - np) / 2;
  257.     *xminp = *xminp - (float)nx * *dist;
  258.     *xmaxp = *xminp + (float)n * *dist;
  259.  
  260.     /*
  261.      * Adjust limits to account for round-off if necessary
  262.      */
  263.  
  264.     if (*xminp > xmin)
  265.         *xminp = xmin;
  266.  
  267.     if (*xmaxp < xmax)
  268.         *xmaxp = xmax;
  269. }
  270.  
  271. /*
  272.  *    Algorithm 463 scale1 (from CACM)
  273.  *    given min, max and n, scaleaxis finds a new range minp and
  274.  *    maxp divisible into approximately n linear intervals
  275.  *    of size dist
  276.  *    vint is an array of acceptable values for dis (times
  277.  *    an integer power of 10)
  278.  *    sqr is an array of geometric neans of adjacent values
  279.  *    of vint, it is used as break points to determine
  280.  *    which vint value to assign to dist
  281.  *
  282.  */
  283. linscale1(min, max, n, minp, maxp, dist)
  284.     float    min, max, *minp, *maxp, *dist;
  285.     int    n;
  286. {
  287.     static float    vint[] = { 1.0, 2.0, 5.0, 10.0 };
  288.     static float    sqr[] = { 1.414214, 3.162278, 7.071068 };
  289.     float        fn, a, al, b, fm1;
  290.     int        i,nal,m1;
  291.  
  292.     /*
  293.      *    check whether proper input values were supplied 
  294.      */
  295.  
  296.     if (min > max || n < 0) {
  297.         fprintf(stderr," improper input supplied to linscale1 %f %f %d\n",
  298.             min, max, n);
  299.         exit(1);
  300.     }
  301.  
  302.     fn = (float) n;
  303.  
  304.     /*
  305.      *    find approximate interval size a 
  306.      */
  307.  
  308.     a = (max - min) / fn;
  309.     if (fabs(a) < 0.000001) {
  310.         max += 1.0;
  311.         min -= 1.0;
  312.         a = (max - min) / fn;
  313.     }
  314.  
  315.     al = log10((double)a);
  316.     nal = (int) al;
  317.     if (a < 1.0) 
  318.         nal -= 1;
  319.  
  320.     /*
  321.      *    a is scaled into variable named b between 1 and 10 
  322.      */
  323.  
  324.     b = a / ten2pow(nal);
  325.  
  326.     /*    
  327.      *    the closest permissible value for b is found 
  328.      */
  329.  
  330.     for (i = 0; b > sqr[i] && i < 3; i++)
  331.         ;
  332.  
  333.     /*
  334.      *    the interval size is computed  
  335.      */
  336.  
  337.       *dist = vint[i] * ten2pow(nal);
  338.     fm1 = min / *dist;
  339.  
  340.     m1 = fm1;
  341.  
  342.     if (fm1 < 0.0) 
  343.         m1 -= 1;
  344.  
  345.     if (ABS((m1 + 1.0 - fm1)) < del) 
  346.         m1 += 1;
  347.  
  348.     /*
  349.      *    the new minimum and maximum limits are found
  350.      */
  351.  
  352.     *minp = *dist * (float)m1;
  353.  
  354.     fm1 = max / *dist;
  355.     m1 = (int)(fm1 + 1.0);
  356.  
  357.     if (fm1 < -1.0 || ABS((fm1 + 1.0 - (float)m1)) < del)
  358.         m1 -= 1;
  359.  
  360.     *maxp = *dist * (float)m1;
  361.  
  362.     /*
  363.      *    adjust limits to account for round-off if necessary 
  364.      */
  365.  
  366.     if (*minp > min) 
  367.         *minp = min;
  368.     if (*maxp < max)
  369.         *maxp = max;
  370.  
  371. }
  372.